home *** CD-ROM | disk | FTP | other *** search
- #ifndef _POOL_C_
- #define _POOL_C_
- /*
- * $RCSfile: Pool.c,v $
- * $Revision: 1.1.1.1 $
- * $Date: 1996/05/04 21:55:09 $
- */
- /**********************************************************************
- * EXODUS Database Toolkit Software
- * Copyright (c) 1991 Computer Sciences Department, University of
- * Wisconsin -- Madison
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * THE COMPUTER SCIENCES DEPARTMENT OF THE UNIVERSITY OF WISCONSIN --
- * MADISON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION.
- * THE DEPARTMENT DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
- * WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * The EXODUS Project Group requests users of this software to return
- * any improvements or extensions that they make to:
- *
- * EXODUS Project Group
- * c/o David J. DeWitt and Michael J. Carey
- * Computer Sciences Department
- * University of Wisconsin -- Madison
- * Madison, WI 53706
- *
- * or exodus@cs.wisc.edu
- *
- * In addition, the EXODUS Project Group requests that users grant the
- * Computer Sciences Department rights to redistribute these changes.
- **********************************************************************/
-
-
- #ifndef __GNUC__
- #include "sysdefs.h"
- #include "checking.h"
- #include "ess.h"
- #include "list.h"
- #include "Pool.h"
- #include "trace.h"
- #include "error.h"
- #endif __GNUC__
-
- template <class CONTENTS>
- void
- Pool<CONTENTS>:: listMake(
- LIST *list, /* already initialized, list of elements to create */
- LIST *mallocList, /* already initialized, list of malloc-ed areas */
- int howMany
- )
- {
- register int i;
- register char *c;
- CONTENTS *contents;
- LISTELEMENT *element;
- int numbytes = sizeof(LISTELEMENT) + (howMany * elementSize);
-
- /* First: malloc space for one LISTELEMENT (to point to the
- * malloced space to be freed), and for all the LISTELEMENTS
- * and CONTENTS structures needed for the pool.
- */
-
- c = (char *) malloc( numbytes );
- if(c == NULL) {
- SM_ERROR(TYPE_FATAL, esmMALLOCFAILED);
- }
- TRPRINT(TR_BF, TR_LEVEL_1, ("malloced area 0x%x",c));
- nmallocs++;
- spaceRequirement += numbytes;
- bzero(c, numbytes);
-
- /*
- * Put on the mallocList:
- * one LISTELEMENT pointing to this free-able segment
- */
- element = (LISTELEMENT *)c;
- initializeListElement(element, c);
- listEnq(mallocList, element);
- c += sizeof(LISTELEMENT);
-
-
- /* Now create a pool of CONTENTS, linked through their LISTELEMENTS
- * (each CONTENTS type must contain a list, which we find by the
- * listlocation() member function of the parameter class)
- */
- for (contents = (CONTENTS *)c,i = 0; i < howMany; i++) {
- contents->Init();
- element = contents->listlocation(this->unique);
-
- /* contents->Init() should have initialized ALL list elements,
- * so we do not need to do this:
- * initializeListElement( element, (char *)contents );
- */
- listEnq(list, element);
- contents++;
- }
- totalQty += howMany;
- } /* listMake */
-
- template <class CONTENTS>
- Pool<CONTENTS>::Pool (
- char *name,
- int which,
- int howMany,
- FLAGS flags
- )
- {
- TRPRINT(TR_BF, TR_LEVEL_1, ("new pool :%s", name));
-
- initializeList( &this->freeList );
- initializeList( &this->mallocedList );
-
- (void) bzero(this->name, sizeof(this->name));
- { int length;
- length = strlen(name);
- if(length >= sizeof(this->name))
- length = sizeof(this->name)-1;
-
- (void) strncpy(this->name, name, length);
- }
-
- this->unique = which;
-
- this->maxUsed = this->currentUsed = 0;
- this->totalQty = 0;
-
- this->elementSize = sizeof(CONTENTS);
- this->spaceRequirement = this->nmallocs = 0;
- this->flags = flags;
- this->lastMallocedQty = howMany;
-
- listMake(&this->freeList, &this->mallocedList, howMany);
- } /* constructor */
-
- template <class CONTENTS>
- Pool<CONTENTS>::~Pool ()
- {
- register char *freeableArea;
-
- /* dispose of all malloc-ed areas */
-
- TRPRINT(TR_BF, TR_LEVEL_1, ("~Pool %s", this->name ));
- if(LIST_EMPTY( &(this->mallocedList) ) )
- return;
-
- while ((freeableArea =
- (char *) listDeq( &(this->mallocedList) )) != NULL) {
- free((char *)freeableArea);
- }
- TRPRINT(TR_BF, TR_LEVEL_1, ("End ~Pool %s", this->name ));
- } /* destructor */
-
- template <class CONTENTS>
- CONTENTS *
- Pool<CONTENTS>::Get()
- {
- register CONTENTS *contents;
-
- TRPRINT(TR_BF, TR_LEVEL_1, ("Get from :%s", this->name));
-
- CHECK_LIST_MAGIC(&freeList);
-
- if (LIST_EMPTY( &freeList) ) {
-
- if (flags & POOL_NOMORE_GETMORE ) {
- /* try to get again as much */
- /* later, we might want to try different amounts */
- listMake(&this->freeList, &this->mallocedList, this->lastMallocedQty);
- } else {
- if (flags & POOL_NOMORE_ISFATAL ) {
- SM_ERROR(TYPE_FATAL, esmPOOLEMPTY);
- } else if (flags & POOL_NOMORE_ISERROR ) {
- SM_ERROR(TYPE_LOG, esmPOOLEMPTY);
- }
- return(NULL);
- }
- }
- if ((contents = (CONTENTS *) listDeq( &(freeList) )) == NULL) {
- SM_ERROR(TYPE_FATAL, esmINTERNAL);
- }
- currentUsed++;
-
- if (currentUsed > maxUsed) {
- maxUsed = currentUsed;
- }
-
- TRPRINT(TR_BF, TR_LEVEL_2, ("contents:%x", contents));
-
- contents->ReInit();
-
- return( contents );
- }
-
- template <class CONTENTS>
- void
- Pool<CONTENTS>::ForEach(
- int nargs, /* TOTAL # args, including func */
- #ifndef __GNUC__
- FOREACHFUNC foreachfunc,
- #endif __GNUC__
- ...
- )
- {
- va_list ap;
- #define MAXNARGS 10
- void *arglist[MAXNARGS];
- LISTELEMENT *listelement ;
- LISTELEMENT *next ;
- #ifdef __GNUC__
- FOREACHFUNC foreachfunc;
- #endif __GNUC__
-
- TRPRINT(TR_BF, TR_LEVEL_1, ("ForEach :%s", this->name));
- #ifdef __GNUC__
- SM_ASSERT(LEVEL_1, (nargs <= MAXNARGS));
- #endif __GNUC__
-
- SM_ASSERT(LEVEL_1, (nargs >= 1)); /* must include func */
- {
- register int i;
-
- #ifdef __GNUC__
- va_start(ap,nargs);
- foreachfunc = va_arg(ap,FOREACHFUNC);
- #else
- va_start(ap,foreachfunc);
- #endif __GNUC__
-
- for(i=0; i<nargs; i++) {
- arglist[i] = va_arg(ap,void *);
- TRPRINT(TR_BF, TR_LEVEL_1,
- ("arglist[%d]=0x%x", i, arglist[i]));
- }
- va_end(ap);
- }
-
- for( listelement = FIRST_LIST_ELEMENT_ITSELF( &(freeList) );
- listelement != &(freeList); listelement = next) {
-
- /* Get the next list element before calling the function.
- * That way, if the function removes the list element from
- * the list, we can still function properly.
- * We will not catch new elements, should the function
- * cause new elements to be added to the list.
- */
- next = NEXT_LIST_ELEMENT_ITSELF( listelement );
- if((*foreachfunc)(listelement->item,
- arglist[0], arglist[1], arglist[2], arglist[3],
- arglist[4], arglist[5], arglist[6], arglist[7],
- arglist[8], arglist[9]))
- return;
- }
- }
-
- template <class CONTENTS>
- void
- Pool<CONTENTS>::Put( /* counterpart to listEnq */
- CONTENTS *contents
- )
- {
- register LISTELEMENT *element = contents->listlocation(this->unique);
-
- TRPRINT(TR_BF, TR_LEVEL_1, ("Put Pool:%s element:%x", name, element));
-
- CHECK_LIST_MAGIC( &freeList );
- INIT_LIST_MAGIC(element);
-
- /* ERROR if element is in a list already */
- listEnq( &freeList, element );
-
- currentUsed--;
- }
-
- template <class CONTENTS>
- void
- Pool<CONTENTS>::Move( /* counterpart to listMoveEnq */
- CONTENTS *contents
- )
- {
- register LISTELEMENT *element = contents->listlocation(this->unique);
- TRPRINT(TR_BF, TR_LEVEL_1, ("Pool:%s element:%x", name, element));
-
- CHECK_LIST_MAGIC(&freeList);
- INIT_LIST_MAGIC(element);
-
- /* ERROR if element is NOT in a list already */
- listMoveEnq( &freeList, element );
-
- currentUsed--;
- }
-
- template <class CONTENTS>
- void
- Pool<CONTENTS>::Stats( FILE *f )
- #ifdef DEBUG
- /*
- * these ifdefs look funny because g++ (2.3.1) has a bug
- * in adding line directive to template functions.
- */
- {
- #else
- {
- #endif DEBUG
- fprintf(f, "Pool %s: %d malloc%s for %d elements\n",
- name, nmallocs, nmallocs==1?"":"s", totalQty);
- fprintf(f, "\t usage: highwater=%d, in use now=%d\n",
- maxUsed, currentUsed);
-
- #ifndef DEBUG
- }
- #else
- {
- int i=0;
- register LISTELEMENT *listelement;
-
- if(LIST_EMPTY( &(this->mallocedList)) )
- return;
-
- listelement = FIRST_LIST_ELEMENT_ITSELF( &(this->mallocedList) );
- while (listelement != &(this->mallocedList) ) {
- i++;
- /* fprintf(stderr, "malloced area 0x%x\n", listelement->item); */
- listelement = NEXT_LIST_ELEMENT_ITSELF( listelement);
- }
- /* fprintf(stderr, "total areas %d\n", i); */
- }
- }
- #endif DEBUG
- #endif /* _POOL_C_ */
-